package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.dao.PaasProcessDataDao;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.FieldPermissionEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateNodeEntityExt;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.model.PaasProcessTemplateNodeModel;
import com.xbongbong.paas.script.pojo.FundAccountExplainsDTO;
import com.xbongbong.paas.script.pojo.dto.InitProcessDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.FundAccountEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.InvoiceEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.model.FundAccountModel;
import com.xbongbong.sys.model.CompanyModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author yuqian
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/fund/process")
public class FundProcessNodeController {
    private static final Logger LOG = LoggerFactory.getLogger(FundProcessNodeController.class);
    @Resource
    PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private PaasProcessTemplateNodeModel paasProcessTemplateNodeModel;
    @Resource
    private PaasProcessDataDao paasProcessDataDao;
    @Resource
    private FundAccountModel fundAccountModel;

    /**
     * @throws Exception
     */
    @RequestMapping(value = "/initProcess", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initDemo(@RequestBody @Valid InitProcessDTO initProcessDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(initProcessDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = initProcessDTO.getCorpidList();
        List<String> attrList = initProcessDTO.getAttrList();
        if (CollectionsUtil.isEmpty(attrList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        if ( CollectionsUtil.isEmpty(corpidList) ) {
            corpidList = companyModel.getCorpidList();
        }
        LOG.info("共有" + corpidList.size() + "家数据");
        Integer i = 0;
        if(CollectionsUtil.isNotEmpty(corpidList)) {
            for (String corpid : corpidList) {
                i++;
                LOG.info("现在是第" + i + "家公司");
                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("businessType", initProcessDTO.getBusinessType());
                params.put("del", 0);
                params.put("corpid", corpid);
                List<PaasProcessTemplateEntityExt> templateEntities = paasProcessTemplateModel.list(params);
                if (!templateEntities.isEmpty()) {
                    for (PaasProcessTemplateEntityExt templateEntity : templateEntities) {
                        params.remove("corpidList");
                        params.put("corpid", templateEntity.getCorpid());
                        params.put("templateId", templateEntity.getId());
                        List<PaasProcessTemplateNodeEntityExt> nodeEntityList = paasProcessTemplateNodeModel.list(params);
                        List<PaasProcessTemplateNodeEntityExt> nodeEntities = new ArrayList<>();
                        for (PaasProcessTemplateNodeEntityExt nodeEntityExt : nodeEntityList) {
                            PaasProcessTemplateNodeEntityExt paasProcessTemplateNodeEntity = new PaasProcessTemplateNodeEntityExt();
                            paasProcessTemplateNodeEntity.setId(nodeEntityExt.getId());
                            List<FieldPermissionEntityExt> fieldPermissions = nodeEntityExt.getFieldPermissionList();
                            List<FieldPermissionEntityExt> addPermissions = new ArrayList<>();
                            if (fieldPermissions != null) {
                                boolean isHavePaymentRelationShip = false;
                                boolean isHavePaymentSheet = false;
                                for (int j=0;j<fieldPermissions.size();j++) {
                                    FieldPermissionEntityExt fieldPermission = fieldPermissions.get(j);
                                    if(!Objects.equals(InvoiceEnum.PAYMENT_RELATIONSHIP.getAttr(),fieldPermission.getAttr())) {
                                        if(j == fieldPermissions.size()-1){
                                            if(!isHavePaymentRelationShip) {
                                                FieldPermissionEntityExt fieldPermissionEntityExt = new FieldPermissionEntityExt();
                                                fieldPermissionEntityExt.setAttr(InvoiceEnum.PAYMENT_RELATIONSHIP.getAttr());
                                                fieldPermissionEntityExt.setEditable(BasicConstant.ZERO);
                                                fieldPermissionEntityExt.setVisible(BasicConstant.ONE);
                                                fieldPermissionEntityExt.setFieldType(InvoiceEnum.PAYMENT_RELATIONSHIP.getFieldType());
                                                fieldPermissionEntityExt.setSubAttr("");
                                                fieldPermissionEntityExt.setSummary(BasicConstant.ZERO);
                                                addPermissions.add(fieldPermissionEntityExt);
                                            }
                                        }
                                    }else {
                                        isHavePaymentRelationShip = true;
                                    }
                                    if(!Objects.equals(InvoiceEnum.PAYMENT_SHEET_ID.getAttr(),fieldPermission.getAttr())) {
                                        if(j == fieldPermissions.size()-1){
                                            if(!isHavePaymentSheet) {
                                                FieldPermissionEntityExt fieldPermissionEntityExt = new FieldPermissionEntityExt();
                                                fieldPermissionEntityExt.setAttr(InvoiceEnum.PAYMENT_SHEET_ID.getAttr());
                                                fieldPermissionEntityExt.setEditable(BasicConstant.ZERO);
                                                fieldPermissionEntityExt.setVisible(BasicConstant.ONE);
                                                fieldPermissionEntityExt.setFieldType(InvoiceEnum.PAYMENT_SHEET_ID.getFieldType());
                                                fieldPermissionEntityExt.setSubAttr("");
                                                fieldPermissionEntityExt.setSummary(BasicConstant.ZERO);
                                                addPermissions.add(fieldPermissionEntityExt);
                                            }
                                        }
                                    }else {
                                        isHavePaymentSheet = true;
                                    }
                                }
                                fieldPermissions.addAll(addPermissions);
                                for (FieldPermissionEntityExt fieldPermission : fieldPermissions) {
                                    if (attrList.contains(fieldPermission.getAttr())) {
                                        if (Objects.nonNull(initProcessDTO.getVisible())) {
                                            fieldPermission.setVisible(initProcessDTO.getVisible());
                                        }
                                        if (Objects.nonNull(initProcessDTO.getEditable())) {
                                            fieldPermission.setEditable(initProcessDTO.getEditable());
                                        }
                                    }
                                }

                            }
                            paasProcessTemplateNodeEntity.setFieldPermission(JSON.toJSONString(fieldPermissions));
                            nodeEntities.add(paasProcessTemplateNodeEntity);
                        }
                        paasProcessTemplateNodeModel.updateBatch(nodeEntities, templateEntity.getCorpid());
                    }
                }
            }
        }
        LOG.warn("-----------处理完毕-----------");
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }

    /**
     * @throws Exception
     */
    @RequestMapping(value = "/account/initProcessNode", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initProcessNode(@RequestBody @Valid InitProcessDTO initProcessDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(initProcessDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        long timeStart = DateTimeUtil.getInt();
        List<String> corpidList = initProcessDTO.getCorpidList();
        if ( CollectionsUtil.isEmpty(corpidList) ) {
            corpidList = companyModel.getCorpidList();
        }
        Integer businessType = initProcessDTO.getBusinessType();
        if (!Objects.equals(businessType, XbbRefTypeEnum.PAYMENT_SHEET.getCode()) && !Objects.equals(businessType, XbbRefTypeEnum.PAY_SHEET.getCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        LOG.info("共有" + corpidList.size() + "家数据");
        Integer i = 0;
        if(CollectionsUtil.isNotEmpty(corpidList)) {
            for (String corpid : corpidList) {
                i++;
                LOG.info("现在是第" + i + "家公司");
                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("businessType", businessType);
                params.put("del", 0);
                params.put("corpid", corpid);
                List<PaasProcessTemplateEntityExt> templateEntities = paasProcessTemplateModel.list(params);
                if (!templateEntities.isEmpty()) {
                    for (PaasProcessTemplateEntityExt templateEntity : templateEntities) {
                        params.remove("corpidList");
                        params.put("corpid", templateEntity.getCorpid());
                        params.put("templateId", templateEntity.getId());
                        List<PaasProcessTemplateNodeEntityExt> nodeEntityList = paasProcessTemplateNodeModel.list(params);
                        List<PaasProcessTemplateNodeEntityExt> nodeEntities = new ArrayList<>();
                        for (PaasProcessTemplateNodeEntityExt nodeEntityExt : nodeEntityList) {
                            PaasProcessTemplateNodeEntityExt paasProcessTemplateNodeEntity = new PaasProcessTemplateNodeEntityExt();
                            paasProcessTemplateNodeEntity.setId(nodeEntityExt.getId());
                            List<FieldPermissionEntityExt> fieldPermissions = nodeEntityExt.getFieldPermissionList();
                            List<FieldPermissionEntityExt> addPermissions = new ArrayList<>();
                            if (fieldPermissions != null && fieldPermissions.size() > 0) {
                                boolean hasFundAccount = false;
                                boolean updateFlag = false;
                                for (FieldPermissionEntityExt fieldPermission : fieldPermissions) {
                                    if (Objects.equals(businessType, XbbRefTypeEnum.PAYMENT_SHEET.getCode()) && Objects.equals(PaymentSheetEnum.FUND_ACCOUNT.getAttr(), fieldPermission.getAttr())) {
                                        hasFundAccount = true;
                                    }
                                    if (Objects.equals(businessType, XbbRefTypeEnum.PAY_SHEET.getCode())) {
                                        if (Objects.equals(PaySheetEnum.FUND_ACCOUNT.getAttr(), fieldPermission.getAttr())) {
                                            hasFundAccount = true;
                                        }
                                        //把关联供应商、关联采购合同的可编辑置为不可编辑
                                        boolean flag = (Objects.equals(PaySheetEnum.LINK_SUPPLIER.getAttr(), fieldPermission.getAttr()) || Objects.equals(PaySheetEnum.LINK_PURCHASE.getAttr(), fieldPermission.getAttr())) && Objects.equals(fieldPermission.getEditable(), BasicConstant.ONE);
                                        if (flag) {
                                            fieldPermission.setEditable(BasicConstant.ZERO);
                                            updateFlag = true;
                                        }
                                    }
                                }
                                if (!hasFundAccount) {
                                    if (Objects.equals(businessType, XbbRefTypeEnum.PAYMENT_SHEET.getCode())) {
                                        FieldPermissionEntityExt fieldPermissionEntityExt = new FieldPermissionEntityExt();
                                        fieldPermissionEntityExt.setAttr(PaymentSheetEnum.FUND_ACCOUNT.getAttr());
                                        fieldPermissionEntityExt.setEditable(BasicConstant.ZERO);
                                        fieldPermissionEntityExt.setVisible(BasicConstant.ONE);
                                        fieldPermissionEntityExt.setFieldType(PaymentSheetEnum.FUND_ACCOUNT.getFieldType());
                                        fieldPermissionEntityExt.setSummary(BasicConstant.ZERO);
                                        addPermissions.add(fieldPermissionEntityExt);
                                    }else if (Objects.equals(businessType, XbbRefTypeEnum.PAY_SHEET.getCode())) {
                                        FieldPermissionEntityExt fieldPermissionEntityExt = new FieldPermissionEntityExt();
                                        fieldPermissionEntityExt.setAttr(PaySheetEnum.FUND_ACCOUNT.getAttr());
                                        fieldPermissionEntityExt.setEditable(BasicConstant.ZERO);
                                        fieldPermissionEntityExt.setVisible(BasicConstant.ONE);
                                        fieldPermissionEntityExt.setFieldType(PaySheetEnum.FUND_ACCOUNT.getFieldType());
                                        fieldPermissionEntityExt.setSummary(BasicConstant.ZERO);
                                        addPermissions.add(fieldPermissionEntityExt);
                                    }
                                    if (addPermissions.size() > 0 || updateFlag) {
                                        fieldPermissions.addAll(addPermissions);
                                        paasProcessTemplateNodeEntity.setFieldPermission(JSON.toJSONString(fieldPermissions));
                                        nodeEntities.add(paasProcessTemplateNodeEntity);
                                    }
                                }
                            }
                        }
                        if (nodeEntities.size() > 0) {
                            paasProcessTemplateNodeModel.updateBatch(nodeEntities, templateEntity.getCorpid());
                        }
                    }
                }
            }
        }
        LOG.warn("-----------time consume initPaymentSheetAccount:" + (DateTimeUtil.getInt() - timeStart));
        LOG.warn("-----------处理完毕-----------");
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }

    @RequestMapping(value = "/paymentSheet/initProcess/account", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initProcessAccount(@RequestBody @Valid FundAccountExplainsDTO fundAccountExplainsDTO, BindingResult br) throws XbbException {
        String msg;
        if (br.hasErrors()) {
            msg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
        } else {
            if (!proBaseConfig.getXbbCode().equals(fundAccountExplainsDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            long timeStart = DateTimeUtil.getInt();
            List<String> corpidList = fundAccountExplainsDTO.getCorpidList();
            if (CollectionsUtil.isEmpty(corpidList)) {
                corpidList = companyModel.getCorpidList();
            }
            LOG.info("共有" + corpidList.size() + "家数据");
            Integer i = 0;
            if (CollectionsUtil.isNotEmpty(corpidList)) {
                for (String corpid : corpidList) {
                    i++;
                    LOG.info("现在是第" + i + "家公司");
                    Map<String, Object> proceeParams = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    proceeParams.put(StringConstant.CORPID, corpid);
                    if (Objects.equals(fundAccountExplainsDTO.getGreaterOrLess(), 0)) {
                        proceeParams.put("addTimeEnd", fundAccountExplainsDTO.getAddTime());
                    } else if (Objects.equals(fundAccountExplainsDTO.getGreaterOrLess(), 1)) {
                        proceeParams.put("addTimeStart", fundAccountExplainsDTO.getAddTime());
                    } else {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), "大于等于或小于标识错误");
                    }
                    List<PaasProcessDataEntity> templateEntities = paasProcessDataDao.getScriptPaymentSheetData(proceeParams);
                    if (templateEntities.size() == 0) {
                        continue;
                    }
                    Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    params.put("businessType", XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                    params.put("del", 0);
                    params.put("corpid", corpid);
                    List<FundAccountEntity> fundAccounts = fundAccountModel.findEntitys(params);
                    Long accountId = 0L;
                    if (fundAccounts != null && fundAccounts.size() > 0) {
                        accountId = fundAccounts.get(0).getId();
                    }
                    if (!templateEntities.isEmpty()) {
                        List<PaasProcessDataEntity> entityList = new ArrayList<>();
                        for (PaasProcessDataEntity templateEntity : templateEntities) {
                            String dataStr = templateEntity.getData();
                            JSONObject data = JSONObject.parseObject(dataStr);
                            if (!data.containsKey(PaymentSheetEnum.FUND_ACCOUNT.getAttr())) {
                                data.put(PaymentSheetEnum.FUND_ACCOUNT.getAttr(), accountId.toString());
                                templateEntity.setData(data.toJSONString());
                                entityList.add(templateEntity);
                            }
                        }
                        if (entityList.size() > 0) {
                            paasProcessDataDao.updateBatch(entityList, corpid);
                        }
                    }
                }
            }
            LOG.warn("-----------time consume initPaymentSheetAccount:" + (DateTimeUtil.getInt() - timeStart));
            LOG.warn("-----------处理完毕-----------");
            msg = "{\"msg\":\"success\"}";
        }
        return JSON.toJSONString(msg);
    }

    @RequestMapping(value = "/refund/paymentSheet/initProcess/account", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initRefundPaymentSheetProcessAccount(@RequestBody @Valid FundAccountExplainsDTO fundAccountExplainsDTO, BindingResult br) throws XbbException {
        String msg;
        if (br.hasErrors()) {
            msg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
        } else {
            if (!proBaseConfig.getXbbCode().equals(fundAccountExplainsDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            long timeStart = DateTimeUtil.getInt();
            List<PaasProcessDataEntity> templateEntities = paasProcessDataDao.getScriptRefundPaymentSheetData();
            Set<String> corpList = new HashSet<>();
            templateEntities.forEach(e -> corpList.add(e.getCorpid()));
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpidList", corpList);
            param.put("columns", "id,corpid,name");
            List<FundAccountEntity> accounList = fundAccountModel.findEntitys(param);
            Map<String, FundAccountEntity> corpIdToAccountId = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            accounList.forEach(e -> corpIdToAccountId.put(e.getCorpid(), e));
            templateEntities.forEach(e -> {
                String data = e.getData();
                JSONObject dataObj = JSONObject.parseObject(data);
                JSONArray paymentArray = dataObj.getJSONArray(RefundEnum.PAYMENT_SHEETS.getAttr());
                if (paymentArray != null) {
                    for (int i = 0; i < paymentArray.size(); i++) {
                        JSONObject paymentObj;
                        try {
                            paymentObj = paymentArray.getJSONObject(i);
                        } catch (Exception e1) {
                            continue;
                        }
                        if (!paymentObj.containsKey(PaymentSheetEnum.FUND_ACCOUNT.getAttr())) {
                            FundAccountEntity account = corpIdToAccountId.get(e.getCorpid());
                            JSONObject accountObj = new JSONObject();
                            accountObj.put("text", account.getName());
                            accountObj.put("value", account.getId().toString());
                            paymentObj.put(PaymentSheetEnum.FUND_ACCOUNT.getAttr(), accountObj);
                        }
                    }
                }
                String newData = dataObj.toJSONString();
                e.setData(newData);
            });

            paasProcessDataDao.updateBatchByScript(templateEntities);
            LOG.warn("-----------time consume initPaymentSheetAccount:" + (DateTimeUtil.getInt() - timeStart));
            LOG.warn("-----------处理完毕-----------");
            msg = "{\"msg\":\"success\"}";
        }
        return JSON.toJSONString(msg);
    }
}
